//============================================================================
// Name        : Feb24.cpp
// Author      : Anthony Varghese
// Version     : 1
// Copyright   : If you change this, add your name to the list of names for authors
// Description : Simple C++ class with << operator overloading
//============================================================================

#include <iostream>
using namespace std;

class MyData{
public:
    MyData(){name = "default"; }
    MyData(const string s_in){ name = s_in; }
    MyData(const int s){
    	name = "uniform array";
        for (int i=0; i<10; i++)
            cloud[i] = s;
    }
    MyData(const float array[10]){
    	name = "array";
        for (int i=0; i<10; i++)
            cloud[i] = array[i];
    }
    MyData(const string s_in, const float array[10]){
    	name = s_in;
        for (int i=0; i<10; i++)
            cloud[i] = array[i];
    }
    void print() const {
    	cout << name << "   ";
        for (int i=0; i<10; i++)
            cout << cloud[i] << " ";
        cout << endl;
    }
    float get(int index){
    	return cloud[ index ];
    }
    float& operator[](int index) {
    	return cloud[ index ];
    }
    const MyData operator +(const MyData op) const {
    	const string str = name + op.name;
        float result[10];
        for (int i=0; i<10; i++)
            result[i] = cloud[i] + op.cloud[i];
        return MyData( str, result );
    }
    MyData operator -(const MyData& op) const {
        float result[10];
        for (int i=0; i<10; i++)
            result[i] = cloud[i] - op.cloud[i];
        return MyData( result );
    }
    MyData operator -(){
        float result[10];
        for (int i=0; i<10; i++)
            result[i] = - cloud[i];
        return MyData( result );
    }
    MyData operator ++(){ // Prefix
        for (int i=0; i<10; i++)
        	cloud[i] = cloud[i] + 1;
        return MyData( cloud );
    }
    MyData operator ++(int notUsed){ // Postfix
        float result[10];
        for (int i=0; i<10; i++)
            result[i] = cloud[i];
        for (int i=0; i<10; i++)
            cloud[i] = cloud[i] + 1;
        return MyData( result );
    }
    bool operator ==(const MyData& op) const {
    	if (name.compare(op.name) != 0)
    		return false;
    	for (int i=0; i<10; i++)
    		if (cloud[i] != op.cloud[i]) return false;
    	return true;
    }
    friend ostream& operator <<(ostream& out, const MyData& d);
private:
    string name;
    float cloud[ 10 ];
};


int& example(int& input){
	return input;
}

ostream& operator <<(ostream& out, const MyData& d){
	out << d.name;
	for (int i=0; i<10; i++)
		out << " " << d.cloud[ i ];
	return out;
}

int main() {
    MyData x( "Hello" );

    float d[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    MyData y( d );

    x.print();
    y.print();

    MyData z = x + y;

    z.print();

    bool e = x == x;
    cout << "x same as x is " << e << endl;



    int r = 10;
    cout << " r is " << r << endl;
    int& t = r;

    int i=5;
    t = i;
    t++;

    cout << " t is " << t << endl;
    t = 5;
    cout << " t is " << t << endl;
    cout << " r is " << r << endl;

    cout << "r = " << r << endl;
    cout << "r++ " << r++ << endl;
    cout << "++r " << ++r << endl;
// error: lvalue required as increment operand
//    cout << "++r++" << ++r++ << endl;

    cout << " t is " << t << endl;

    cout << endl << "Calling example()" << endl;
    t = example(i);
    cout << " r is " << r << endl;
    example(t) = 20;  // works only if returning by reference
    cout << " r is " << r << endl;


    MyData temp = y;
    cout << "Prefix:" << endl;
    MyData pre = ++y;
    cout << " returned : "; pre.print();
    cout << " y is now : "; y.print();

    y = temp;
    cout << "Postfix:" << endl;
    MyData post = y++;
    cout << " returned : "; post.print();
    cout << " y is now : "; y.print();

    y= temp;
    MyData both = ++(++y++)++;
    cout << " both:  "; both.print();



    cout << "Overloading stream insertion operator" << endl;
    cout << " y is " << y << endl;
    return 0;
}
